package com.knife.permission.plugins;

import com.knife.permission.entity.DataPermission;
import com.knife.permission.plugins.helper.DataPermissionHelper;
import com.knife.permission.plugins.helper.UserDetailHelper;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Properties;

import static com.knife.common.constants.BaseConstants.SqlSymbol.NO_ONE;
import static com.knife.common.constants.BaseConstants.SqlSymbol.SPACE;


/**
 * 数据权限拦截器
 *
 * @author tianhao.luo@hand-china.com
 */
@Component
@Order(value = 100)
@Intercepts(@Signature(
        type = Executor.class,
        method = "query",
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
public class DefaultDataPermissionPlugin implements Interceptor {

    @Autowired
    private DataPermissionHelper dataPermissionHelper;


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        try {
            if (dataPermissionHelper.isPermissionControl(invocation)) {
                if (dataPermissionHelper.isAdmin()) {
                    return invocation.proceed();
                }
                // 获取构造好的权限对象
                DataPermission dataPermission = dataPermissionHelper.getDataPermissionDto(invocation);
                if (dataPermission == null) {
                    // 非管理员角色不能查出任何数据
                    dataPermission = new DataPermission(NO_ONE, SPACE);
                }
                dataPermissionHelper.replaceBoundSql(invocation, dataPermission);
            }
            return invocation.proceed();
        } finally {
            UserDetailHelper.clear();
        }
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof Executor) {
            return Plugin.wrap(target, this);
        } else {
            return target;
        }
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
